/*
 * 2022/1/5	10:52	qing
 */

/*
 * 文件提取过程		P250
 */
	00401BB0 sub esp, 70
	00401BB3 mov eax, ds:[405020]
			 push exb
			 push edi
			 mov edi, ss:[esp+84]
			 push 0
			 mov ss:[esp+78], eax
			 mov eax, ss:[esp+80]
			 push 0
			 push eax
			 push edi
			 call 00401670
			 mov edx, ds:[405048]
			 add esp, 10
			 lea ecx, ss:[esp+14]
			 push ecx
			 push 0
			 push 0
			 push 8003
			 push edx
			 mov ebx, eax
			 call CryptCreateHash
			 test eax, eax
			 jnz short 00401c11
			 push 00403284			; format = "unable to verify the file's hash value!"
			 call ds:[printf]
			 add esp, 4
			 push 1					; status = 1
			 call exit
			 push ebp
			 push esi
			 push 0					; Origin = FILE_BEGIN
			 push 0					; pOffsetHi = NULL
			 push 0					; OffsetLo = 0
			 push ebx				; hFile
			 call SetFilePointer
			 push 0					; pOverlapped = NULL
			 lea eax, ss:[esp+24]
			 push eax				; pBytesRead
			 push 28				; BytesToRead = 0x28 (40)
			 push 00406058			; Buffer = 00406058
			 push ebx				; hFile
			 call ReadFile
			 mov esi, ss:[esp+88]
			 xor ecx, ecx
			 push edi
			 mov ss:[esp+71], ecx
			 lea edx, ss:[esp+70]
			 push edx
			 mov ss:[esp+79], ecx
			 lea eax, ss:[esp+18]
			 push eax
			 mov ss:[esp+81], ecx
			 mov ss:[esp+85], cx
			 push esi
			 push ebx
			 mov dword ptr ss:[esp+24], 0
			 mov ss:[esp+28], esi
			 mov byte ptr ss:[esp+80], 0
			 mov ss:[esp+8f], cl
			 call 004017b0
			 mov edi, ss:[esp+24]
			 push 5c						; c = 5c ('\')
			 push esi						; s
			 mov ss:[esp+34], esi
			 mov esi, ds:[strchr]
			 mov ebp, eax
			 call esi						; strchr
			 add esp, 1c
			 test eax, eax
			 je short 00401cb3
			 mov edi, edi
			 add eax, 1
			 push 5c
			 push eax
			 mov ss:[esp+20], eax
			 call esi
			 add esp, 8
			 test eax, eax
			 jnz short 00401ca0
			 test ebp, ebp
			 jnz short 00401cd2
			 mov ecx, ss:[esp+18]
			 push ecx						; <%s>
			 push 004032b0					; format = "File "%s" not found in archive."
			 call printf
			 add esp, 8
			 push 1							; status = 1
			 call exit
			 mov esi, ss:[esp+14]
			 push 0							; hTemplaterFile = NULL
			 push 0							; Attributes = 0
			 push 2							; Mode = CREATE_ALWAYS
			 push 0							; pSecurity = NULL
			 push 0							; ShareMode = 0
			 push c0000000					; Access = GENERIC_READ|GENERIC_WRITE
			 push esi						; FileName
			 call CreateFileA
			 cmp eax, -1
			 mov ss:[esp+14], eax
			 jnz short 00401d13
			 call GetLastError
			 push eax						; <%d>
			 push esi						; <%s>
			 push 004032d4					; format = "error:unable to create file %s (last error=%d)." 
			 call printf
			 add esp, 0c
			 push 1							; status = 1
			 call exxit
			 mov edx, ss:[esp+8c]
			 push edx
			 push ebp
			 push ebx
			 call 00401030
			 test edi, edi
			 mov ss:[esp+2c], edi
			 fild dword ptr ss:[esp+2c]
			 jge short 00401d34
			 fadd dword ptr ds:[403ba0]
			 fdivr qword ptr ds:[403b98]
			 mov eax, ss:[esp+24]
			 xorps xmm0, xmm0
			 mov ebp, ds:[printf]
			 push eax
			 push 00403308					; ASCII "Extracting "%.35S" - "
			 movss ss:[esp+24], xmm0
			 fstp dword ptr ss:[esp+34]
			 call ebp
			 add esp, 14
			 test edi, edi
			 je 00401e39
			 mov esi, ds:[GetConsoleScreenBufferInfo]
			 lea ebx, ds:[ebx]
			 mov edx, ds:[40504c]
			 lea ecx, ss:[esp+2c]
			 push ecx
			 push edi
			 push esi
			 fld dword ptr ss:[esp+10]
			 sub esp, 8
			 fstp qword ptr ss:[esp]
			 push 00403320					; ascii "%2.2f percent completed."
			 call ebp
			 add esp, 0c
			 cmp edi, 1
			 mov eax, 0ffc
			 ja short 00401da1
			 mov eax, ds:[405050]
			 push 0
			 push eax
			 mov eax, ss:[esp+24]
			 push 00405054
			 push eax
			 call CryptHashData
			 test eax, eax
			 je 00401eee
			 cmp edi, 1
			 mov eax, ffc
			 ja short 00401dcb
			 mov eax, ds:[405050]
			 mov edx, ss:[esp+14]
			 push 0						; pOverlapped = NULL
			 lea ecx, ss:[esp+2c]
			 push ecx					; pBytesWritten
			 push eax					; nBytestoWrite
			 push 00405054				; buffer = 00405054
			 push edx					; hFile
			 call WriteFile
			 sub edi, 1
			 je short 00401e00
			 mov eax, ss:[esp+8c]
			 mov ecx, ds:[405050]
			 push eax
			 push ecx
			 push ebx
			 call 00401030
			 add esp, 0c
			 mov eax, ds:[40504c]
			 lea edx, ss:[esp+44]
			 push edx
			 push eax
			 call esi
			 mov ecx, ss:[esp+30]
			 mov edx, ds:[40504c]
			 push ecx					; CursorPos 
			 push edx						; hConsole = 00000007
			 call SetConsoleCursorPosition
			 test edi, edi
			 movss xmm0, ss:[esp+10]
			 addss xmm0, ss:[esp+20]
			 movss ss:[esp+10], xmm0
			 jnz 00401d70
			 fld qword ptr ds:[403b98]
			 sub esp, 8
			 fstp qword ptr ss:[esp]
			 push 00403368					; ascii "%2.2f percent completed."
			 call ebp
			 push 00403384
			 call ebp
			 xor eax, eax
			 mov ss:[esp+6d], eax
			 mov ss:[esp+71], eax
			 mov ss:[esp+75], eax
			 mov ss:[esp+79], ax
			 add esp, 10
			 lea ecx, ss:[esp+24]
			 lea edx, ss:[esp+5c]
			 mov ss:[esp+6b], al
			 mov byte ptr ss:[esp+5c], 0
			 mov dword ptr ss:[esp+24], 10
			 push eax
			 mov eax, ss:[esp+20]
			 push ecx
			 push edx
			 push 2
			 push eax
			 call CryptGetHashParam
			 test eax, eax
			 jnz short 00401ea0
			 push 00403388			; ascii "unable to obtain MD5 hash value for file."
			 call ebp
			 add esp, 4
			 mov ecx, 4
			 lea edi, ss:[esp+6c]
			 lea esi, ss:[esp+5c]
			 xor edx, edx
			 repe cmps dword ptr es:[edi], dword ptr ds:[esi]
			 je short 00401ec2
			 mov eax, ss:[esp+18]
			 push eax
			 push 004033b4			; ascii "error: file %s is corrupted.!"
			 call ebp
			 add esp, 8
			 mov ecx, ss:[esp+1c]
			 push ecx
			 call CryptDestroyHash
			 mov edx, ss:[esp+14]
			 mov esi, ds:[CloseHandle]
			 push edx					; hObject
			 call esi					; CloseHandle
			 push ebx					; hObject
			 call esi					; CloseHandle
			 mov ecx, ss:[esp+7c]
			 pop esi
			 pop ebp
			 pop edi
			 pop ebx
			 call 004027c9
			 add esp, 70
			 retn


/*
 * 扫描文件列表		P256
 */
	这个函数采用扫描文件列表的惯用方法，并将正要提取的文件名与列表中的每个名字进行比较。一旦找到正确的文件项，函数就从该文件
	项中获取数个字段的信息。

	00401881 mov ecx, ss:[esp+10]
	00401885 lea eax, ds:[esi+esi*4]
			 add eax, eax
			 add eax, eax
			 sub eax, esi
	0040188e mov edx, ds:[ecx+eax*8+8]	# 把计算结果(eax)乘以8后作为索引。这段代码实际上是在对ESI进行运算，也就是当前文件项
										# 的索引，将它乘以"19*8=152".
			 lea eax, ds:[ecx+eax*8]
			 mov ecx, ss:[esp+24]
			 mov ds:[ecx], edx
			 mov ecx, ss:[esp+28]
			 test ecx, ecx
			 je short 004018bc
			 lea edx, ds:[eax+c]
			 mov esi, ds:[edx]
			 mov ds:[ecx], esi
			 mov esi, ds:[edx+4]
			 mov ds:[ecx+4], esi
			 mov esi, ds:[edx+8]
			 mov ds:[ecx+8], esi
			 mov edx, ds:[edx+c]
			 mov ds:[ecx+c], edx
			 mov eax, ds:[eax+4]
	
	显然是一段优化过的算术运算的代码。

	由于使用了LEA，可能带来小小困惑，但是LEA并不是只能对地址进行操作。 00401885 处的LEA实际上就是将ESI乘以5，然后将结果存放
	EAX中。

	回到这段算术运算代码。第一个LEA是将ESI乘以5。紧随其后的是两条ADD所完成的是将ESI的值乘以4放放EAX中。
	再后面一行是ESI乘以20，然后又减去自己的原值，这相当于将ESI乘以19。

/*
 * 解密文件		P256
 */
	00401c9e mov edi, edi

	第五章中看到过类似的指令。那一次，那条指令是为了陷入Windows中的系统API而设置的一条指令。这里的情况显然与此不同，那么编译器为什么要在函数
	的中间插入一个不做任何事情的指令呢？

	答案非常简单：这条指令的开始地址是不对齐的(unaligned)，这就意味着它不是从32位的边界开始的。通过将这样的指令放在循环开始之前，编译器就能确保
	循环不会在从一条未对齐的指令开始执行。另外，要注意的是编译器还可以使用NOP指令----NOP也是什么都不做，只是在代码中精确地填充2个字节的“间隙”，
	也可想想编译器为什么不用NOP呢？


/*
 * 浮点运算代码		P258
 */
	00401D28 fild dword ptr ss:[esp+2c]
			 jge short 004d1d34
			 fadd dword ptr ds:[403ba0]
			 fdivr qwor ptr ds:[403b98]
			 mov eax, ss:[esp+24]
			 xorps xmm0, xmm0
			 mov ebp, ds:[printf]
			 push eax
			 push 00403308
			 movss ss:[esp+24], xmm0
			 fstp word ptr ss:[esp+34]
			 call ebp


/*
 * 解密循环		P260
 */
	00401DBC cmp edi, 1
			 mov eax, 0ffc
			 ja short 00401dcb
			 mov eax, ds:[405050]

